#!/usr/bin/perl -w # for syntax highlighting
package clreqd_modules;

#########################################################################
# This rountine takes the details of an event monitor and loads them	#
# into the local configuration database if they are successfully	#
# validated.								#
#									#
# Arguments are:							#
# type, name, mond							#
# [appname]								#
#									#
# type - the type of the entry should be 'node' or 'app'.		#
# name - the nickname of the monitor.					#
# mond - the hex-encoded XML.						#
# appname - the name of the application [if type is 'app'].		#
#									#
# Returns:								#
# OK - record added/replaced as requested.				#
# ERROR msg - an error has occured - see 'msg'.				#
#########################################################################

use cldb;
use mond_mons;
use mond_actions;
use mond_xml;
use Data::Dumper;

sub set_monitor_info {
my %ARGS=@_;
my $f;

	if(! grep {$_ eq "$::ENV{TRUECL_CODE}/monitors"} @::INC) {
		push @::INC,"$::ENV{TRUECL_CODE}/monitors";
	}
	my $appname=$ARGS{APPNAME} if exists($ARGS{APPNAME});
	my $name=$ARGS{NAME};
	my $type=lc($ARGS{TYPE});
	if($type ne "node" && $type ne "app") {
		return "ERROR Type setting of '$type' is not valid.";
	}
	$type=substr($type,0,1);
	my $mond=pack("h*",$ARGS{MOND});

	# Ok - lets load an XML parser for the monitors...
	#      and also a monitor objects object and a monitors actions
	#      object.

	my $mon_parse=new mond_xml;
	my $mon_monitors=new mond_mons;
	my $mon_actions=new mond_actions;

	mond_xml::set_logmsg_hdlr(\&::msg);
	mond_xml::set_warnmsg_hdlr(\&::warning);
	mond_mons::set_logmsg_hdlr(\&::msg);
	mond_mons::set_warnmsg_hdlr(\&::warning);

	my $actions_ref=$mon_actions->get_valid_actions;
	my $monitors_ref=$mon_monitors->get_valid_node_monitors;
	$mon_parse->set_valid_monitors("node",@{$monitors_ref});
	$monitors_ref=$mon_monitors->get_valid_app_monitors;
	$mon_parse->set_valid_monitors("application",@{$monitors_ref});
	$mon_parse->set_valid_actions(@{$actions_ref});
	# Pass in the data

	{
		my $r;
		eval {$r=$mon_parse->parse($mond);};
		if($@) {
			return "ERROR - Invalid XML found.";
		}
		if(!$r) {
			my $s=$mon_parse->error;
			return "ERROR $s";
		}
	}

	#################################################################
	# Everything is set up - so now we attempt to parse the 	#
	# information passed.						#
	#################################################################

	my @F=$mon_parse->validate_structure;
	if($F[0]==0) {
		return "ERROR " . join("\n",@F[1 .. $#F]);
	}
	
	#################################################################
	# So we've got an xml file in the expected format, so next	#
	# check to see if the contents are valid as well.		#
	#################################################################

	@F=$mon_parse->validate_entries;
	if($F[0]==0) {
		return "ERROR " . join("\n",@F[1 .. $#F]);
	}

	#################################################################
	# So everything is OK - now we just need to write out the 	#
	# new data into the correct table. This is straightforward.	#
	#################################################################

	if(! -f "$::ENV{TRUECL_CFG}/config.db") {
		return("ERROR Failed to find database '$::ENV{TRUECL_CFG}/config.db'!");
	}

	#################################################################
	# Database does exist, so open it up ready for changing.	#
	#################################################################

	my $db=new cldb("$::ENV{TRUECL_CFG}/config.db");
	if(!defined($db)) {
		return("ERROR Unable to open database 'config.db':\n" . cldb::error);
	}
	::msg("Opened database connection to '$::ENV{TRUECL_CFG}/config.db'.");

	#################################################################
	# Ensure the table exists and abort if not.			#
	#################################################################

	if(! $db->exists("table","event_monitor")) {
		return("ERROR Config database missing 'event_monitor' table.");
	}
	my $s="SELECT COUNT(*) as count FROM event_monitor WHERE type = '$type' AND name = '$name' ";
	$s.=" AND appname = '$appname' " if defined($appname);
	$s.=";";
	my $res=$db->get_rows($s);
	if(!defined($res) || !defined($res->[0]->{count})) {
		my $e=cldb::error;
		if(defined($e)) {
			return "ERROR $e";
		} else {
			return "ERROR No count was returned for active monitors!";
		}
	}

	if($res->[0]->{count}) {
		$s="DELETE FROM event_monitor WHERE type = '$type' AND name = '$name' ";
		$s.=" AND appname = '$appname' " if defined($appname);
		$s.=";";
		$r=$db->do($s);
		if(!$r) {
			my $e=cldb::error;
			if(defined($e)) {
				return "ERROR Unable to remove record from database. $e";
			} else {
				return "ERROR Unable to remove record from database.";
			}
		}
	}

	#################################################################
	# Any existing record has been deleted - so new record		#
	# can be added.							#
	#################################################################
	$s="INSERT INTO event_monitor (type,name,appname,xml,update_time) VALUES ('$type','$name',";
	if(defined($appname)) {
		$s.="'$appname',";
	} else {
		$s.="'',";
	}
	$s.=sprintf("'%s','%d');",$ARGS{MOND},time);
	$r=$db->do($s);
	if(!$r) {
		my $e=cldb::error;
		if(defined($e)) {
			return "ERROR Unable to add record to database. $e";
		} else {
			return "ERROR Unable to add record to database.";
		}
	}
	$db->disconnect; $db=undef;
	return "OK";
}

1;
